package com.wangijun.yuan.admin.system.service;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.wangijun.yuan.admin.base.CacheKey;
import com.wangijun.yuan.admin.base.CommonPage;
import com.wangijun.yuan.admin.base.CommonResult;
import com.wangijun.yuan.admin.base.YuanAdminConst;
import com.wangijun.yuan.admin.system.domain.RoleUser;
import com.wangijun.yuan.admin.system.domain.SysUser;
import com.wangijun.yuan.admin.system.mapper.SysUserMapper;
import com.wangijun.yuan.admin.system.model.dto.UserQryParam;
import com.wangijun.yuan.admin.system.model.dto.UserSaveParam;
import com.wangijun.yuan.admin.system.model.dto.UserUpdateParam;
import com.wangijun.yuan.admin.system.model.vo.RoleVO;
import com.wangijun.yuan.admin.system.model.vo.UserVO;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.util.List;

@Service
@CacheConfig(cacheNames = CacheKey.user)
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {
    @Resource
    private SysRoleService roleService;
    @Resource
    private SysSerialService serialService;

    // 默认密码
    final String defaultPasswd = "000000";

    /**
     * 功能描述: 列表数据
     *
     * @author wlf 2023/9/16 21:08
     */
    public CommonPage<UserVO> getList(UserQryParam param) {
        Page<SysUser> page = this.lambdaQuery()
                .like(StrUtil.isNotBlank(param.getName()), SysUser::getName, param.getName())
                .like(StrUtil.isNotBlank(param.getLoginNo()), SysUser::getLoginNo, param.getLoginNo())
                .page(param.page());

        return CommonPage.toPage(page, UserVO.class, vo -> {
            List<RoleVO> roleVOS = roleService.getBaseMapper().getRolesByUserId(vo.getId());
            vo.setRoles(roleVOS);
        });
    }

    /**
     * 功能描述: 获取单个
     *
     * @author wlf 2023/9/16 21:08
     */
    @Cacheable(key = "#id")
    public UserVO get(Long id) {
        SysUser user = this.getById(id);
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        List<RoleVO> roleVOS = roleService.getBaseMapper().getRolesByUserId(userVO.getId());
        userVO.setRoles(roleVOS);
        userVO.setRoleIds(roleVOS.stream().map(RoleVO::getId).toList());
        return userVO;
    }

    /**
     * 功能描述: 获取当前登录用户信息
     *
     * @author wlf 2023/12/4 14:37
     */
    public SysUser getLoginUser() {
        return SpringUtil.getBean(this.getClass()).get(StpUtil.getLoginIdAsLong());
    }

    /**
     * 功能描述: 删除单个
     *
     * @author wlf 2023/9/16 21:08
     */
    @CacheEvict(key = "#id")
    public void del(Long id) {
        checkAdmin(id);
        Db.lambdaUpdate(RoleUser.class)
                .eq(RoleUser::getUserId, id)
                .remove();
        this.removeById(id);
    }

    /**
     * 重置密码
     */
    @CacheEvict(key = "#id")
    public void reset(Long id) {
        this.lambdaUpdate()
                .set(SysUser::getPssswd, YuanAdminConst.md5.digestHex16(defaultPasswd))
                .eq(SysUser::getId, id).update();
    }

    /**
     * 功能描述: 批量删除
     *
     * @author wlf 2023/9/16 21:08
     */
    @Transactional(rollbackFor = Exception.class)
    public void delBatch(List<Long> ids) {
        for (Long id : ids) {
            checkAdmin(id);
            SpringUtil.getBean(this.getClass()).del(id);
        }
    }


    /**
     * 校验是否为Admin用户
     */
    private void checkAdmin(Long id) {
        if (1L == id) {
            CommonResult.error("Admin用户不可删除");
        }
    }

    /**
     * 功能描述: 添加用户
     *
     * @author wlf 2023/9/16 21:09
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(UserSaveParam param) {
        SysUser sysUser = BeanUtil.copyProperties(param, SysUser.class);
        sysUser.setId(IdWorker.getId());
        for (Long roleId : param.getRoleIds()) {
            RoleUser roleUser = new RoleUser();
            roleUser.setUserId(sysUser.getId());
            roleUser.setRoleId(roleId);
            Db.save(roleUser);
        }
        sysUser.setPssswd(YuanAdminConst.md5.digestHex16(defaultPasswd));
        sysUser.setLoginNo(serialService.getSerial(YuanAdminConst.SerialType.LOGIN_NO));
        sysUser.setCreateTime(LocalDateTime.now());
        this.save(sysUser);
    }

    /**
     * 功能描述: 更新用户
     *
     * @author wlf 2023/9/16 21:09
     */
    @Caching(
            evict = {
                    @CacheEvict(cacheNames = CacheKey.power, key = "#param.id"),
                    @CacheEvict(key = "#param.id")
            }
    )
    @Transactional(rollbackFor = Exception.class)
    public void update(UserUpdateParam param) {
        SysUser sysUser = BeanUtil.copyProperties(param, SysUser.class);
        // 先删除
        Db.lambdaUpdate(RoleUser.class).eq(RoleUser::getUserId, sysUser.getId()).remove();
        for (Long roleId : param.getRoleIds()) {
            RoleUser roleUser = new RoleUser();
            roleUser.setUserId(sysUser.getId());
            roleUser.setRoleId(roleId);
            Db.save(roleUser);
        }
        this.updateById(sysUser);
    }
}
